package com.zqh.generator.main;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.zqh.generator.JarGenerator;
import com.zqh.generator.ScriptGenerator;
import com.zqh.generator.file.DynamicFileGenerator;
import com.zqh.meta.Meta;
import com.zqh.meta.MetaManager;
import freemarker.template.TemplateException;
import lombok.var;

import java.io.IOException;

public class MainGenerator {

    public static void GenerateTemplate(boolean isDist) throws TemplateException,
            IOException, InterruptedException {

        // 1、获取源信息
        Meta meta = MetaManager.getMetaObject();
//        System.out.println(meta);

        // 2、获取路径
        String outputPath = getPath(meta);

        // 3、复制原始文件
        String sourceCopyDesPath = copySource(meta, outputPath);

        // 4、读取Resources文件
        String inputResourcePath = getInputResourcePath();

        // 5、获取java基础包
        String outputBaseJavaPackagePath = getOutputBaseJavaPackagePath(meta, outputPath);

        // 6、代码生成
        generateCode(inputResourcePath, outputBaseJavaPackagePath, meta, outputPath);

        // 7、生成jar包
        JarGenerator.doGenerate(outputPath);

        // 8、封装脚本
        shellResult result = getShellResult(outputPath, meta);

        // 9、生成精简版
        String disOutPutPath = "";
        if (isDist) {
            disOutPutPath = buildDist(outputPath, result, sourceCopyDesPath);
            // 压缩文件
            String zipPath = buildZip(disOutPutPath);
        }
    }

    protected static String buildDist(String outputPath, shellResult result, String sourceCopyDesPath) {
        String disOutPutPath = outputPath + "-dist";
        // 拷贝jar包
        String targetAbsolutePath = disOutPutPath + "/" + "target";
        FileUtil.mkdir(targetAbsolutePath);
        String jarAbsolutePath = outputPath + "/" + result.jarPath;
        FileUtil.copy(jarAbsolutePath, targetAbsolutePath, true);
        // 拷贝脚本文件
//        FileUtil.copy(shellOutputFilepath,disOutPutPath,true);
        FileUtil.copy(result.shellOutputFilepath, disOutPutPath, true);
        // 拷贝模板文件
        FileUtil.copy(sourceCopyDesPath, disOutPutPath, true);

        return disOutPutPath;
    }

    private static shellResult getShellResult(String outputPath, Meta meta) {
        String shellOutputFilepath = outputPath + "/" + "generator";
        String jarName = String.format("%s-%s-jar-with-dependencies.jar", meta.getName(), meta.getVersion());
        String jarPath = "target/" + jarName;
        ScriptGenerator.doGenerate(shellOutputFilepath, jarPath);
        var result = new shellResult(shellOutputFilepath, jarPath);
        return result;
    }

    protected static class shellResult {
        public final String shellOutputFilepath;
        public final String jarPath;

        public shellResult(String shellOutputFilepath, String jarPath) {
            this.shellOutputFilepath = shellOutputFilepath;
            this.jarPath = jarPath;
        }
    }

    private static void generateCode(String inputResourcePath, String outputBaseJavaPackagePath, Meta meta, String outputPath) throws IOException, TemplateException {
        // 文件输入输出路径
        String inputFilePath;
        String outPutFilePath;

        // model.DataModel
        inputFilePath = inputResourcePath + "templates/java/model/DataModel.java.ftl";
        outPutFilePath = outputBaseJavaPackagePath + "/" + "model/DataModel.java";
        DynamicFileGenerator.doGenerate(inputFilePath, outPutFilePath, meta);

        // cli.command.GenerateCommand
        inputFilePath = inputResourcePath + "templates/java/cli/command/GenerateCommand.java.ftl";
        outPutFilePath = outputBaseJavaPackagePath + "/" + "cli/command/GenerateCommand.java";
        DynamicFileGenerator.doGenerate(inputFilePath, outPutFilePath, meta);

        // cli.command.ListCommand
        inputFilePath = inputResourcePath + "templates/java/cli/command/ListCommand.java.ftl";
        outPutFilePath = outputBaseJavaPackagePath + "/" + "cli/command/ListCommand.java";
        DynamicFileGenerator.doGenerate(inputFilePath, outPutFilePath, meta);

        // cli.command.ConfigCommand
        inputFilePath = inputResourcePath + "templates/java/cli/command/ConfigCommand.java.ftl";
        outPutFilePath = outputBaseJavaPackagePath + "/" + "cli/command/ConfigCommand.java";
        DynamicFileGenerator.doGenerate(inputFilePath, outPutFilePath, meta);

        // cli.CommandExecutor
        inputFilePath = inputResourcePath + "templates/java/cli/CommandExecutor.java.ftl";
        outPutFilePath = outputBaseJavaPackagePath + "/" + "cli/CommandExecutor.java";
        DynamicFileGenerator.doGenerate(inputFilePath, outPutFilePath, meta);

//        // main
        inputFilePath = inputResourcePath + "templates/java/Main.java.ftl";
        outPutFilePath = outputBaseJavaPackagePath + "/" + "Main.java";
        DynamicFileGenerator.doGenerate(inputFilePath, outPutFilePath, meta);


        // generator.DynamicGenerator
        inputFilePath = inputResourcePath + "templates/java/generator/DynamicGenerator.java.ftl";
        outPutFilePath = outputBaseJavaPackagePath + "/" + "generator/DynamicGenerator.java";
        DynamicFileGenerator.doGenerate(inputFilePath, outPutFilePath, meta);

        // generator.StaticGenerator
        inputFilePath = inputResourcePath + "templates/java/generator/StaticGenerator.java.ftl";
        outPutFilePath = outputBaseJavaPackagePath + "/" + "generator/StaticGenerator.java";
        DynamicFileGenerator.doGenerate(inputFilePath, outPutFilePath, meta);

//        // generator.MainGenerator
        inputFilePath = inputResourcePath + "templates/java/generator/FileGenerator.java.ftl";
        outPutFilePath = outputBaseJavaPackagePath + "/" + "generator/FileGenerator.java";
        DynamicFileGenerator.doGenerate(inputFilePath, outPutFilePath, meta);

        // pom.xml
        inputFilePath = inputResourcePath + "templates/pom.xml.ftl";
        outPutFilePath = outputPath + "/" + "pom.xml";
        DynamicFileGenerator.doGenerate(inputFilePath, outPutFilePath, meta);

        // README.md
        inputFilePath = inputResourcePath + "templates/README.md.ftl";
        outPutFilePath = outputPath + "/" + "README.md";
        DynamicFileGenerator.doGenerate(inputFilePath, outPutFilePath, meta);
    }

    private static String getOutputBaseJavaPackagePath(Meta meta, String outputPath) {
        String outputBasePackage = meta.getBasePackage();
        String outputBasePackagePath = StrUtil.join("/", StrUtil.split(outputBasePackage, "."));
        String outputBaseJavaPackagePath = outputPath + "/" + "src/main/java/" + outputBasePackagePath;
        return outputBaseJavaPackagePath;
    }

    private static String getInputResourcePath() {
        var resource = new ClassPathResource("");
        String inputResourcePath = resource.getAbsolutePath();
        return inputResourcePath;
    }

    private static String getPath(Meta meta) {
        // 输出跟路径
        String projectPath = System.getProperty("user.dir");
        String outputPath = projectPath + "/" + "generated" + "/" + meta.getName();
        // 如果目录不存在，创建目录
        if (!FileUtil.exist(outputPath)) {
            FileUtil.mkdir(outputPath);
        }
        return outputPath;
    }

    private static String copySource(Meta meta, String outputPath) {
        // 复制source里的文件
        String sourceRootPath = meta.getFileConfig().getSourceRootPath();
        String sourceCopyDesPath = outputPath + "/" + ".source";
        FileUtil.copy(sourceRootPath, sourceCopyDesPath, false);
        return sourceCopyDesPath;
    }

    /**
     * 构建zip
     *
     * @param outputPath
     * @return
     */
    protected static String buildZip(String outputPath) {

        String zipPath = outputPath + ".zip";

        ZipUtil.zip(outputPath, zipPath);

        return zipPath;
    }


}
